<?php
/**
 * User: bgl
 * Date: 2023/6/20
 * Time: 16:46
 */
namespace App\Admin\Controllers\Products;

use App\Admin\Actions\Products\Material\BatchStatusClose;
use App\Admin\Actions\Products\Material\BatchStatusOpen;
use App\Admin\Ajax\Products\MaterialAjax;
use App\Admin\Extensions\Grid\Tool\Export;
use App\Models\Basics\SupplierM;
use App\Models\Product\ProductMaterial;
use App\Models\Product\ProductMaterialApplicationClassify;
use App\Models\Product\ProductMaterialApply;
use App\Models\Product\ProductMaterialClassifyMax;
use App\Models\Product\ProductMaterialClassifyMin;
use App\Models\Product\ProductMaterialContainer;
use App\Util\RExcel;
use App\Util\User;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Illuminate\Support\Facades\Request;

class MaterialController extends AdminController{

    protected $title = '材料建档';

    protected function grid(){

        $grid = new Grid(new ProductMaterial());
        $grid->model()->orderBy('ID', 'DESC');
        $grid->column('material_code','材料编码');
        $grid->column('title','材料名称');
        $grid->column('title1','材料名称(材质)');
        $grid->column('title2','材料名称(规格)');
        $grid->column('title3','材料名称(工艺/功能)');
        $grid->column('material_application_classify_id','应用品类')->display(function ($value){
            $arr = [];
            if(!empty($value)){
                foreach ($value as $key => $id){
                    $arr[] = ProductMaterialApplicationClassify::getValueById($id,'title');
                }
            }
            return $arr ? implode('、', $arr) : '';
        });
        $grid->column('material_classify_max.title','材料大类');
        $grid->column('material_classify_min.title','材料小类');
        $grid->column('supplier.code','在库供应商编码');
        $grid->column('supplier.name','在库供应商名称');
        $grid->column('supplier_title','(临时)供应商名称');
        $grid->column('container_no','货柜号')->display(function ($value){
            $arr = [];
            if(!empty($value)){
                foreach ($value as $key => $functionId){
                    $arr[] = ProductMaterialContainer::getValueById($functionId,'code');
                }
            }
            return $arr ? implode('、', $arr) : '';
        });
        $grid->column('admin_id','建档人')->display(function ($value){
            return $value ? User::getUsernameById($value) : '';
        });;
        $grid->column('review_status','品质评审')->bool([ProductMaterial::REVIEW_YES => true, ProductMaterial::REVIEW_NO => false]);
        $grid->column('status','是否使用')->bool([ProductMaterial::STATUS_YES => true, ProductMaterial::STATUS_NO => false]);
        $grid->column('操作')->view('products.material.action');

        $grid->fixHeader();
        $grid->paginate(10);
        $grid->fixColumns(0,-1);
        $grid->disableExport();
        $grid->disableActions();
        $grid->tools(function (Grid\Tools $tools){
            $tools->append(new Export('products/material-download'));
        });

        $grid->batchActions(function ($batch) {
            $batch->add(new BatchStatusOpen());
            $batch->add(new BatchStatusClose());
            $batch->disableDelete();
        });

        $grid->filter(function($filter){
            $filter->column(1/2, function ($filter){
                $filter->where(function ($query) {
                    $query->where('material_code', 'like', "%{$this->input}%")
                        ->orWhere('title', 'like', "%{$this->input}%");
                }, '查询','material8')->placeholder('模糊查询编码，名称');
                $filter->contains('material_application_classify_id', '应用品类')->select(ProductMaterialApplicationClassify::options());
                $filter->in('status', '是否使用')->checkbox(ProductMaterial::$_status);
            });

            $filter->column(1/2, function ($filter){
                $filter->equal('material_classify_max_id', '材料大类')->select(ProductMaterialClassifyMax::options());
                $filter->equal('material_classify_min_id', '材料小类')->select(ProductMaterialClassifyMin::options());
                //$filter->equal('admin_id','建档人')->select(User::getCUserOptions());
                $filter->where(function ($query) {
                    $query->where('supplier_title', 'like', "%{$this->input}%");
                }, '临时、在库供应商名称查询','supplier8')->placeholder('模糊查询临时、在库供应商名称');
                $filter->equal('supplier_id', '在库材料供应商')->select(SupplierM::options());
            });
        });

        return $grid;
    }

    public function ajax(){
        $action = request('action');
        $param = request('param');
        $ajax = new MaterialAjax();
        return $param ? call_user_func([$ajax,$action],$param) : call_user_func([$ajax,$action]);
    }

    public function modal(){
        $action = request('action');
        $param = request('param');
        $modal = new MaterialAjax();
        return $param ? call_user_func([$modal,$action],$param) : call_user_func([$modal,$action]);
    }

    protected function form(){
        $form = new Form(new ProductMaterial());
        $form->hidden('id');
        $form->hidden('material_code');

        if ($form->isCreating()) {
            $form->tab('材料', function ($form) {
                $form->hidden('title','材料名称')->required();
                $form->text('title1','材料名称1')->required()->help('材质')->placeholder('请输入材料：材质');
                $form->text('title2','材料名称2')->required()->help('规格')->placeholder('请输入材料：规格');
                $form->text('title3','材料名称3')->required()->help('工艺（功能）')->placeholder('请输入材料：工艺（功能）');
                $form->multipleSelect('material_application_classify_id', '应用品类')
                    ->options(ProductMaterialApplicationClassify::options())
                    ->required();
                $form->select('material_classify_max_id', '材料大类')
                    ->options(ProductMaterialClassifyMax::options())
                    ->load('material_classify_min_id', '/xqc/api-sys/classify-min')
                    ->required();
                $form->select('material_classify_min_id', '材料小类')->required();
                $form->select('admin_id','建档人')->options(User::getCUserOptions())->default(Admin::user()->id);
                $form->multipleSelect('container_no','柜号')->options(ProductMaterialContainer::options());
                $form->text('apply_no','申请单号')->default(request('apply_no'))->help('若存在申请单号，可输入单号进行关联材料');
                $form->switch('review_status', '品质评审')->states(statusSwitch())->default(ProductMaterial::REVIEW_NO);
                $form->switch('status', '是否使用')->states(statusSwitch())->default(ProductMaterial::STATUS_NO);
            });
            $form->tab('供应商', function ($form) {
                $form->select('supplier_id','在库供应商')->options(SupplierM::options())->default(0)->help('若存在材料供应商，请选择供应商进行关联');
                $form->text('supplier_title','(临时)供应商名称')->help('若无可选择供应商，可暂时填写供应商名称');
                $form->decimal('quote_price','报价');
                $form->select('quote_currency','报价单位')->options(ProductMaterial::$_quote_currency);
            });
            $form->tab('规格-1', function ($form) {
                $form->text('specification','规格');
                $form->text('function','功能性');
                $form->text('test_remark','测试标准和要求');
                $form->text('unit','单位');
                $form->text('composition','成分');
                $form->text('test_data','测试数据');
                $form->select('test_after','后整理')->options(ProductMaterial::$_test_after);
                $form->text('spec','材料规格参数');
            });
            $form->tab('规格-2', function ($form) {
                $form->text('yarn_count','纱支');
                $form->number('weight','克重(g/㎡)')->min(0)->width(5);
                $form->number('door_width','门幅')->min(0)->width(5);
                $form->select('door_unit','门幅单位')->options(ProductMaterial::$_door_unit);
                $form->number('coloring_cycle','打色周期')->min(0)->width(5);
                $form->number('devlop_moq','开发MOQ（米）')->min(0)->width(5);
                $form->number('devlop_cylce','开发周期（天）')->min(0)->width(5);
                $form->number('moq','大货MOQ（米）')->min(0)->width(5);
                $form->number('cylce','大货周期（天）')->min(0)->width(5);
                $form->number('grey_cloth','坯布数量（米）')->min(0)->width(5);
            });
        }

        if ($form->isEditing()) {

            $form->tab('材料', function ($form) {
                $form->hidden('title','材料名称')->readonly();
                $form->text('title1','材料名称1')->help('材质')->placeholder('请输入材料：材质');
                $form->text('title2','材料名称2')->help('规格')->placeholder('请输入材料：规格');
                $form->text('title3','材料名称3')->help('工艺（功能）')->placeholder('请输入材料：工艺（功能）');

                $form->multipleSelect('material_application_classify_id', '应用品类')
                    ->options(function (){
                        $id = $this->material_application_classify_id ?: old('material_application_classify_id');
                        $query = ProductMaterialApplicationClassify::query();
                        if ($id) $query->whereIn('id',$id);
                        $classify = $query->pluck('title','id');
                        if($classify->isNotEmpty()) {
                            return $classify->toArray();
                        }else{
                            return [];
                        }
                    })
                    //->readonly()
                    ->required();

                $form->select('material_classify_max_id', '材料大类')
                    ->options(ProductMaterialClassifyMax::options())
                    ->readonly()
                    ->load('material_classify_min_id', '/xqc/api-sys/classify-min')
                    ->required();
                $form->select('material_classify_min_id', '材料小类')
                    ->readonly()
                    ->options(function (){
                        $parentId = $this->material_classify_max_id ?: old('material_classify_max_id');
                        $classifyMin = ProductMaterialClassifyMin::options(['parent_id' => $parentId]);
                        if($classifyMin->isNotEmpty()) {
                            return $classifyMin->toArray();
                        }else{
                            return [];
                        }
                    })->required();
                $form->select('admin_id','建档人')->readonly()->options(User::getCUserOptions());
                $form->multipleSelect('container_no','柜号')->options(ProductMaterialContainer::options());
                $form->text('apply_no','申请单号')->readonly()->help('若存在申请单号，可输入单号进行关联材料');
                $form->switch('review_status', '品质评审')->states(statusSwitch())->default(ProductMaterial::REVIEW_NO);
                $form->switch('status', '是否使用')->states(statusSwitch())->default(ProductMaterial::STATUS_NO);
            });
            $form->tab('供应商', function ($form) {
                $form->select('supplier_id','在库供应商')->options(SupplierM::options())->help('若存在材料供应商，请选择供应商进行关联');
                $form->text('supplier_title','(临时)供应商名称')->help('若无可选择供应商，可暂时填写供应商名称');
                $form->decimal('quote_price','报价');
                $form->select('quote_currency','报价单位')->options(ProductMaterial::$_quote_currency);
            });
            $form->tab('规格-1', function ($form) {
                $form->text('specification','规格');
                $form->text('function','功能性');
                $form->text('test_remark','测试标准和要求');
                $form->text('unit','单位');
                $form->text('composition','成分');
                $form->text('test_data','测试数据');
                $form->select('test_after','后整理')->options(ProductMaterial::$_test_after);
                $form->text('spec','材料规格参数');
            });
            $form->tab('规格-2', function ($form) {
                $form->text('yarn_count','纱支');
                $form->number('weight','克重(g/㎡)')->min(0)->width(5);
                $form->number('door_width','门幅')->min(0)->width(5);
                $form->select('door_unit','门幅单位')->options(ProductMaterial::$_door_unit);
                $form->number('coloring_cycle','打色周期')->min(0)->width(5);
                $form->number('devlop_moq','开发MOQ（米）')->min(0)->width(5);
                $form->number('devlop_cylce','开发周期（天）')->min(0)->width(5);
                $form->number('moq','大货MOQ（米）')->min(0)->width(5);
                $form->number('cylce','大货周期（天）')->min(0)->width(5);
                $form->number('grey_cloth','坯布数量（米）')->min(0)->width(5);
            });
        }

        $form->saving(function (Form $form) {
            if ($form->supplier_id) {
                //存在正式供应商时，替换临时供应商
                $form->supplier_title = SupplierM::getNameById($form->supplier_id) ?? '';
            }

            if ($form->isEditing()) {
                $title = $form->title1 . $form->title2 . $form->title3;
                $form->title = $title;
            }

            if ($form->isCreating()) {
                $title = $form->title1 . $form->title2 . $form->title3;
                $form->title = $title;
                /*****************材料编码 start**************************/
                $classifyMaxCode = ProductMaterialClassifyMax::getValueById($form->material_classify_max_id,'code');
                if (!$classifyMaxCode) {
                    admin_error('ERROR', '材料大类不存在');
                    return back()->withInput();
                }
                $classifyMidCode = ProductMaterialClassifyMin::getValueById($form->material_classify_min_id,'code');
                if (!$classifyMidCode) {
                    admin_error('ERROR', '材料小类不存在');
                    return back()->withInput();
                }

                //材料编码(设置编码规则)
                $newMaterailCode = self::getMaterialCode($classifyMaxCode, $classifyMidCode);
                $existMaterial = ProductMaterial::getValueByCode($newMaterailCode,'id');
                if ($existMaterial) {
                    admin_error('ERROR', '材料编码已存在，请重新设置编码规则');
                    return back()->withInput();
                }
                $form->material_code = $newMaterailCode;
                /*****************材料编码 end**************************/
            }
        });

        $form->saved(function (Form $form) {
            //单号存在,回写材料申请单中的材料id
            if ($form->model()->apply_no) {
                $apply = ProductMaterialApply::query()->where('apply_no',$form->model()->apply_no)->first();
                if ($apply) {
                    $apply->material_id = $form->model()->id; //材料id
                    $apply->material_code = $form->model()->material_code; //材料编码
                    $apply->status = ProductMaterialApply::STATUS_YES; //入库(已使用)
                    $apply->save();
                }
            }
        });

        $form->tools(function (Form\Tools $tools) {
            $tools->disableView();
            $tools->disableDelete();
        });
        return $form;
    }

    public function download(){
        $request = Request::input();
        $query = $this->_initQuery($request);
        $this->_exeDownload($query);
    }

    private function _initQuery($filters){
        $query = ProductMaterial::query()->orderBy('id', 'DESC');
        foreach ($filters as $key => $_filter){
            if($key == 'material8'){
                $query->where(function ($query) use($_filter){
                    $query->where('material_code', 'like', "%{$_filter}%")
                        ->orWhere('title', 'like', "%{$_filter}%");
                });
            }
            if($key == 'supplier8'){
                $query->where(function ($query) use($_filter){
                    $query->where('supplier_title', 'like', "%{$_filter}%");
                });
            }

            if($key == 'material_application_classify_id'){
                $query->where(function ($query) use($_filter){
                    $query->where('material_application_classify_id', 'like', "%{$_filter}%");
                });
            }

            if($key == 'status'){
                $query->whereIn($key,$_filter);
            }
            if(in_array($key,[
                'material_classify_max_id',
                'material_classify_min_id',
                'supplier_id',
                'admin_id',
            ])){
                $query->where($key,$_filter);
            }
        }
        return $query;
    }

    private function _exeDownload($query){
        $head = ['材料编码','材料名称','材料名称(材质)','材料名称(规格)','材料名称(工艺)','应用品类','材料大类','材料小类',
            '材料供应商编码','材料供应商名称','(临时)供应商名称','柜号','柜号','是否启用','创建人','创建时间'];
        RExcel::exportCsv('材料列表', function () use ($head, $query) {
            $fp = fopen('php://output', 'w');
            fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF));
            fputcsv($fp, $head);
            $query->chunk(1000, function ($re) use ($fp){
                $data = self::getDownloadData($re);
                foreach ($data as $item) {
                    fputcsv($fp, $item);
                }
            });
        });
    }

    public static function getDownloadData($res){

        $containerArr = ProductMaterialContainer::options()->toArray();
        $classifyArr = ProductMaterialApplicationClassify::options()->toArray();
        foreach ($res as $model){
            //柜号
            $containerStr = '';
            if($model->container_no){
                $container = [];
                foreach ($model->container_no as $key => $containerId){
                    $container[] = $containerArr[$containerId];
                }
                $containerStr = implode('、', $container);
            }
            //品类
            $classifyStr = '';
            if($model->material_application_classify_id){
                $arr = [];
                foreach ($model->material_application_classify_id as $key => $id){
                    $arr[] = $classifyArr[$id];
                }
                $classifyStr = implode('、', $arr);
            }

            $temp = [
                $model->material_code,
                $model->title,
                $model->title1,
                $model->title2,
                $model->title3,
                $classifyStr ?? '',
                $model->material_classify_max->title ?? '',
                $model->material_classify_min->title ?? '',
                $model->supplier->code ?? '',
                $model->supplier->name ?? '',
                $model->supplier_title ?? '',
                $containerStr,
                ProductMaterial::$_status[$model->status] ?? '',
                User::getUsernameById($model->admin_id) ?? '',
                $model->created_at,
            ];
            yield $temp;
        }
    }

    /**
     * 材料编码
     * @param $classifyMaxCode
     * @param $classifyMidCode
     * @return string
     */
    public static function getMaterialCode($classifyMaxCode, $classifyMidCode){
        //(当前)编码前缀
        $befoceCodeStr = $classifyMaxCode . $classifyMidCode; //前缀，前三位(大类编码首字母+中类编码)

        //(当前)编码尾数
        $materialCode = ProductMaterial::query()->where('material_code', 'like', "%{$befoceCodeStr}%")->max('material_code'); //获取最后一次的编码
        if ($materialCode) {
            $lastNumber = intval(substr($materialCode, -4)) + 1; //尾数累计加1)
        }else{
            $lastNumber = 1; //尾数初始值(从1开始累计)
        }
        $afterCodeStr = str_pad($lastNumber, 4, '0', STR_PAD_LEFT); //尾数，后四位（补位填充数字）

        //材料编码规则(7位数)：材料大类编码(第1位) + 材料中类编码(第2~3位) + 累加数值(最后4位)
        return $befoceCodeStr . $afterCodeStr; //新材料编码
    }
}
